"""DNS相关模型."""

from datetime import datetime
from typing import Optional

from sqlalchemy import (
    Boolean,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from .base import Base


class DNSView(Base):
    """DNS视图模型（用于分割DNS）."""
    
    __tablename__ = "dns_view"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
    description: Mapped[Optional[str]] = mapped_column(Text)
    match_clients: Mapped[Optional[str]] = mapped_column(Text)  # ACL定义
    
    # 关联
    zones: Mapped[list["DNSZone"]] = relationship(
        "DNSZone", back_populates="view", cascade="all, delete-orphan"
    )


class DNSZone(Base):
    """DNS区域模型."""
    
    __tablename__ = "dns_zone"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    name: Mapped[str] = mapped_column(String(255), nullable=False)  # 区域名称
    zone_type: Mapped[str] = mapped_column(
        String(10), 
        default="master", 
        nullable=False
    )  # master, slave, forward
    
    # SOA记录信息
    primary_ns: Mapped[str] = mapped_column(String(255), nullable=False)
    admin_email: Mapped[str] = mapped_column(String(255), nullable=False)
    serial: Mapped[int] = mapped_column(Integer, default=1)
    refresh: Mapped[int] = mapped_column(Integer, default=3600)
    retry: Mapped[int] = mapped_column(Integer, default=900)
    expire: Mapped[int] = mapped_column(Integer, default=86400)
    minimum_ttl: Mapped[int] = mapped_column(Integer, default=3600)
    
    # 区域传输
    allow_transfer: Mapped[Optional[str]] = mapped_column(Text)  # 逗号分隔的IP
    allow_update: Mapped[Optional[str]] = mapped_column(Text)  # 逗号分隔的IP
    
    # 状态
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    is_dynamic: Mapped[bool] = mapped_column(Boolean, default=False)
    
    # 外键关联
    view_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("dns_view.id"), nullable=True
    )
    
    # 关联
    view: Mapped[Optional["DNSView"]] = relationship("DNSView", back_populates="zones")
    records: Mapped[list["DNSRecord"]] = relationship(
        "DNSRecord", back_populates="zone", cascade="all, delete-orphan"
    )
    
    # 约束
    __table_args__ = (
        UniqueConstraint("name", "view_id", name="uq_zone_name_view"),
        Index("idx_zone_view", "view_id"),
        Index("idx_zone_active", "is_active"),
    )
    
    def bump_serial(self) -> None:
        """增加序列号."""
        self.serial += 1


class DNSRecord(Base):
    """DNS记录模型."""
    
    __tablename__ = "dns_record"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    name: Mapped[str] = mapped_column(String(255), nullable=False)  # 记录名称
    record_type: Mapped[str] = mapped_column(
        String(10), 
        nullable=False
    )  # A, AAAA, CNAME, MX, TXT, NS, PTR, SOA
    
    # 记录值
    value: Mapped[str] = mapped_column(Text, nullable=False)
    ttl: Mapped[int] = mapped_column(Integer, default=3600)
    priority: Mapped[Optional[int]] = mapped_column(Integer)  # MX记录使用
    
    # 外键关联
    zone_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("dns_zone.id"), nullable=False
    )
    ip_address_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("ip_address.id"), nullable=True
    )
    
    # 状态
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    
    # 关联
    zone: Mapped["DNSZone"] = relationship("DNSZone", back_populates="records")
    ip_address: Mapped[Optional["IPAddress"]] = relationship("IPAddress")
    
    # 约束
    __table_args__ = (
        UniqueConstraint("name", "record_type", "value", "zone_id", name="uq_record"),
        Index("idx_record_zone", "zone_id"),
        Index("idx_record_type", "record_type"),
        Index("idx_record_name", "name"),
        Index("idx_record_active", "is_active"),
    )
    
    @property
    def fqdn(self) -> str:
        """获取完全限定域名."""
        if self.name == "@":
            return self.zone.name
        elif self.zone.name.endswith("."):
            return f"{self.name}.{self.zone.name}"
        else:
            return f"{self.name}.{self.zone.name}."
    
    @property
    def is_address_record(self) -> bool:
        """检查是否为地址记录（A或AAAA）."""
        return self.record_type in ["A", "AAAA"]
    
    @property
    def is_reverse_record(self) -> bool:
        """检查是否为反向记录（PTR）."""
        return self.record_type == "PTR"